
import RobotError from "../errors/robot-error.js";
import REDIS from "../../util/redis.js";
import Player from "./player.js";
import Item from "../item/item.js";



export default class PlayerManager {
	private playersMap: Map<number, Player>;

	private static playerManager = new PlayerManager();
	static getInstance() {
		return this.playerManager;
	}

	private constructor() {
		this.playersMap = new Map();
	}

	/**
	 * 通过QQ号获取玩家
	 * @param {number} qqNum 
	 * @returns 
	 */
	async getPlayerByQQNum(qqNum: number) {
		if (this.playersMap.has(qqNum)) {
			let player = this.playersMap.get(qqNum);
			await this.loadPlayer(player, qqNum);//同步数据库的数据
			return player;
		}

		//内存中无玩家信息则从磁盘获取
		let player = new Player();
		await this.loadPlayer(player, qqNum);

		//添加玩家至内存
		this.playersMap.set(qqNum, player);
		return player;
	}

	/**
	 * 从磁盘中加载玩家
	 * @param {number} qqNum 
	 * @returns 玩家
	 */
	async loadPlayer(player: Player, qqNum: number) {
		let psl = new PlayerStatusLoader(qqNum);
		player.qqNum = qqNum;

		//加载基础信息
		let nick = await psl.getPlayerStatu("nick", "无名氏");
		let coin = Number.parseInt(await psl.getPlayerStatu("coin"));//硬币
		let totalExp = Number.parseInt(await psl.getPlayerStatu("total_exp"));//总经验
		let hpRatio = Number.parseFloat(await psl.getPlayerStatu("hp_ratio", 1));//目前生命倍率

		//违法数据判断
		let hasErr = false;
		if (isNaN(coin)) {
			coin = 0;
			hasErr = true;
		}
		if (isNaN(totalExp)) {
			totalExp = 0;
			hasErr = true;
		}
		if (isNaN(hpRatio)) {
			hpRatio = 1;
			hasErr = true;
		}
		if (hasErr) throw new RobotError(`玩家${player.qqNum}的数据丢失`);



		// player.coinMember = new CoinM(player, 0);
		// player.fightMember = new FightM(player);
		// player.purchaseMember = new PurchaseM(player);
		// player.expMember = new ExpM(player);
		// player.fightStatusMember = new FightStatusM(player);

		//赋值给玩家类
		player.nick = nick;
		player.coin = coin;
		player.totalExp = totalExp;
		player.hpRatio = hpRatio;

		let items = await psl.getPlayerAllHashStatu("items");
		for (let itemClassName in items) {
			player.itemMember.setItemCount(new Item.map[itemClassName](), Number.parseInt(items[itemClassName]));
		}

		// await this.savePlayer(player);
		return player;
	}
	/**
	 * 保存玩家到磁盘
	 * @param {Player} player 
	 */
	async savePlayer(player: Player) {
		let qqNum = player.qqNum;

		let psl = new PlayerStatusLoader(qqNum);
		await psl.setPlayerStatu("coin", player.coin);
		await psl.setPlayerStatu("total_exp", player.totalExp);
		await psl.setPlayerStatu("hp_ratio", player.hpRatio);
		await psl.setPlayerStatu("nick", player.nick);

		let items = {};
		player.itemMember.items.forEach((count, item) => {
			items[item.constructor.name] = count;
		});
		await psl.setPlayerAllHashStatu(`items`, items);

		// logger.info(`存储玩家数据：${qqNum}`);
	}
}

class PlayerStatusLoader {
	private qqNum: number;
	constructor(qqNum: number) {
		this.qqNum = qqNum;
	}

	async getPlayerStatu(statuName: string, defaultValue: any = 0) {
		let value = await REDIS.get(`LNE:players:${this.qqNum}:${statuName}`);
		if (value == null) value = defaultValue;
		// logger.mark(`加载了${this.qqNum}的${statuName}：${value}`);
		return value;
	}
	async setPlayerStatu(statuName: string, value: any) {
		await REDIS.set(`LNE:players:${this.qqNum}:${statuName}`, value);
		await REDIS.sAdd(`LNE:list:player_qq_num`, '' + this.qqNum);
		// logger.mark(`保存了${this.qqNum}的${statuName}：${value}`);
	}

	async getPlayerAllHashStatu(statuName: string): Promise<{}> {
		let value = await REDIS.hGetAll(`LNE:players:${this.qqNum}:${statuName}`);
		// logger.mark(`加载了${this.qqNum}的${statuName}：${value}`);
		return value;
	}
	async setPlayerAllHashStatu(statuName: string, value: {}) {
		for (let valueKey in value) {
			await REDIS.hSet(`LNE:players:${this.qqNum}:${statuName}`, valueKey, value[valueKey]);
			console.log(`${this.qqNum}: ${statuName}, ${valueKey}, ${value[valueKey]}`);
		}
		await REDIS.sAdd(`LNE:list:player_qq_num`, '' + this.qqNum);
		// logger.mark(`保存了${this.qqNum}的${statuName}：${value}`);
	}
}